﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FarseerGames.FarseerPhysics.Mathematics;
using FreeGoo.GameEngine.Behaviors;
using FreeGoo.GameEngine.Interfaces;

namespace FreeGoo.GameEngine.Renderables
{
    public abstract class Renderable
    {
        private IList<Behavior> _behaviors;

        public Renderable()
        {
            Identifier = null;
        }

        public Engine Engine { get; set; }
        public IRenderer Renderer { get; set; }
        public bool ScheduledForDelete { get; set; }
        public string Identifier { get; set; }
        public abstract Vector2 Position { get; set; }
        public abstract float Rotation { get; set; }

        public float DistanceTo(Renderable renderable)
        {
            return Vector2.Distance(Position, renderable.Position);
        }

        public virtual void Delete()
        {
            Engine.Renderables.Remove(this);
            if (Renderer != null)
            {
                Renderer.Delete();
            }
        }

        public virtual void Selected(Vector2 cursorPosition)
        {
        }

        public virtual void DeSelected()
        {
        }

        /// <summary>
        /// Executes every timestep.
        /// </summary>
        public virtual void UpdatePhysics()
        {
        }

        /// <summary>
        /// Executes every render timestep.
        /// </summary>
        public virtual void UpdateGraphics()
        {
            if (Renderer != null)
            {
                Renderer.Update();
            }

            if (_behaviors != null)
            {
                UpdateBehaviors();
            }
        }

        public void AddBehavior(Behavior behavior)
        {
            if (_behaviors == null)
            {
                _behaviors = new List<Behavior>();
            }

            if (!_behaviors.Contains(behavior))
            {
                _behaviors.Add(behavior);
            }
        }

        public virtual void AddToEngine(Engine engine)
        {
            Engine = engine;
            engine.Renderables.Add(this);
            engine.RendererFactory.SetRenderer(this);
        }

        public virtual void SignalStateChanged()
        {
            if (Renderer != null)
            {
                Renderer.StateChanged();
            }
        }
        
        private void UpdateBehaviors()
        {
            foreach (Behavior behavior in _behaviors)
            {
                behavior.Update();
            }
        }
    }
}
